home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / program / mui32dev.lha / MUI / Developer / Modula / Demo / txt / Class3.mod < prev   
Text File  |  1995-11-13  |  11KB  |  341 lines

  1. MODULE Class3 ;
  2.  
  3. (*$ RangeChk := FALSE *)
  4.  
  5. FROM SYSTEM     IMPORT  TAG, ADR, ADDRESS, LONGSET, CAST, SETREG, REG ;
  6. FROM AmigaLib   IMPORT  DoSuperMethodA ;
  7. FROM ExecL      IMPORT  Wait ;
  8.  
  9. IMPORT
  10.         R,
  11.         gd  : GraphicsD,
  12.         gl  : GraphicsL,
  13.         id  : IntuitionD,
  14.         il  : IntuitionL,
  15.         m   : MuiD,
  16.         mc  : MuiClasses,
  17.         ml  : MuiL,
  18.         mm  : MuiMacros,
  19.         ms  : MuiSupport,
  20.         ud  : UtilityD,
  21.         ul  : UtilityL ;
  22.  
  23. (***************************************************************************)
  24. (* Here is the beginning of our new class...                               *)
  25. (***************************************************************************)
  26.  
  27. (*
  28. ** This is the instance data for our custom class.
  29. *)
  30.  
  31. TYPE
  32.   Data  = RECORD
  33.             x,
  34.             y,
  35.             sx,
  36.             sy : INTEGER ;
  37.           END (* RECORD *) ;
  38.  
  39. (*
  40. ** AskMinMax method will be called before the window is opened
  41. ** and before layout takes place. We need to tell MUI the
  42. ** minimum, maximum and default size of our object.
  43. *)
  44.  
  45. (*/// "mAskMinMax(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpAskMinMaxPtr) : ADDRES" *)
  46.  
  47. PROCEDURE mAskMinMax(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpAskMinMaxPtr) : ADDRESS;
  48.  
  49. BEGIN
  50.   (*
  51.   ** let our superclass first fill in what it thinks about sizes.
  52.   ** this will e.g. add the size of frame and inner spacing.
  53.   *)
  54.  
  55.   IF DoSuperMethodA(cl, obj, msg) # NIL THEN END ;
  56.  
  57.   (*
  58.   ** now add the values specific to our object. note that we
  59.   ** indeed need to *add* these values, not just set them!
  60.   *)
  61.  
  62.   INC(msg^.MinMaxInfo^.MinWidth, 100) ;
  63.   INC(msg^.MinMaxInfo^.DefWidth, 120) ;
  64.   INC(msg^.MinMaxInfo^.MaxWidth, 500) ;
  65.  
  66.   INC(msg^.MinMaxInfo^.MinHeight, 40) ;
  67.   INC(msg^.MinMaxInfo^.DefHeight, 90) ;
  68.   INC(msg^.MinMaxInfo^.MaxHeight, 300) ;
  69.  
  70.   RETURN NIL ;
  71. END mAskMinMax ;
  72.  
  73. (*\\\*)
  74.  
  75. (*
  76. ** Draw method is called whenever MUI feels we should render
  77. ** our object. This usually happens after layout is finished
  78. ** or when we need to refresh in a simplerefresh window.
  79. ** Note: You may only render within the rectangle
  80. **       _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj).
  81. *)
  82.  
  83. (*/// "mDraw(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpDrawPtr) : ADDRES" *)
  84.  
  85. PROCEDURE mDraw(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpDrawPtr) : ADDRESS;
  86.  
  87. VAR
  88.   data : POINTER TO Data ;
  89.  
  90. BEGIN
  91.   data := mc.InstData(cl, obj) ;
  92.  
  93.   (*
  94.   ** let our superclass draw itself first, area class would
  95.   ** e.g. draw the frame and clear the whole region. What
  96.   ** it does exactly depends on msg->flags.
  97.   **
  98.   ** Note: You *must* call the super method prior to do
  99.   ** anything else, otherwise msg->flags will not be set
  100.   ** properly !!!
  101.   *)
  102.  
  103.   IF DoSuperMethodA(cl, obj, msg) # NIL THEN END ;
  104.  
  105.   (*
  106.   ** if MADF_DRAWOBJECT isn't set, we shouldn't draw anything.
  107.   ** MUI just wanted to update the frame or something like that.
  108.   *)
  109.  
  110.   IF mc.drawUpdate IN msg^.flags THEN
  111.     IF (data^.sx # 0) OR (data^.sy # 0) THEN
  112.       gl.SetBPen(mc.OBJ_rp(obj),mc.OBJ_dri(obj)^.pens^[id.shinePen]) ;
  113.       gl.ScrollRaster(mc.OBJ_rp(obj),data^.sx,data^.sy,mc.OBJ_mleft(obj),mc.OBJ_mtop(obj),mc.OBJ_mright(obj),mc.OBJ_mbottom(obj));
  114.       gl.SetBPen(mc.OBJ_rp(obj),0);
  115.       data^.sx := 0;
  116.       data^.sy := 0;
  117.     ELSE
  118.       gl.SetAPen(mc.OBJ_rp(obj),mc.OBJ_dri(obj)^.pens^[id.shadowPen]);
  119.       IF gl.WritePixel(mc.OBJ_rp(obj),data^.x,data^.y) THEN END ;
  120.     END (* IF *) ;
  121.   ELSIF mc.drawObject IN msg^.flags THEN
  122.     gl.SetAPen(mc.OBJ_rp(obj),mc.OBJ_dri(obj)^.pens^[id.shinePen]);
  123.     gl.RectFill(mc.OBJ_rp(obj),mc.OBJ_mleft(obj),mc.OBJ_mtop(obj),mc.OBJ_mright(obj),mc.OBJ_mbottom(obj));
  124.   END (* IF *) ;
  125.  
  126.   RETURN NIL ;
  127. END mDraw ;
  128.  
  129. (*\\\*)
  130. (*/// "mSetup(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpHandleInputPtr) : ADDRES" *)
  131.  
  132. PROCEDURE mSetup(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpHandleInputPtr) : ADDRESS;
  133.  
  134. BEGIN
  135.   IF DoSuperMethodA(cl, obj, msg) = NIL THEN RETURN LONGINT(FALSE) END ;
  136.  
  137.   ml.moRequestIDCMP(obj,id.IDCMPFlagSet{id.mouseButtons, id.rawKey}) ;
  138.   RETURN LONGINT(TRUE) ;
  139. END mSetup ;
  140.  
  141. (*\\\*)
  142. (*/// "mCleanup(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpHandleInputPtr) : ADDRES" *)
  143.  
  144. PROCEDURE mCleanup(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpHandleInputPtr) : ADDRESS;
  145.  
  146. BEGIN
  147.   ml.moRejectIDCMP(obj,id.IDCMPFlagSet{id.mouseButtons, id.rawKey}) ;
  148.  
  149.   RETURN DoSuperMethodA(cl, obj, msg) ;
  150. END mCleanup;
  151.  
  152. (*\\\*)
  153. (*/// "mHandleInput(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpHandleInputPtr) : ADDRES" *)
  154.  
  155. PROCEDURE mHandleInput(cl : id.IClassPtr; obj : id.ObjectPtr; msg : mc.mpHandleInputPtr) : ADDRESS;
  156.  
  157.   PROCEDURE Between(a, x, b : LONGINT) : BOOLEAN ;
  158.   BEGIN
  159.     RETURN (x >= a) AND (x <= b) ;
  160.   END Between ;
  161.  
  162.   PROCEDURE IsInObject(x, y : LONGINT) : BOOLEAN ;
  163.   BEGIN
  164.     RETURN Between(mc.OBJ_mleft(obj), x, mc.OBJ_mright(obj)) AND Between(mc.OBJ_mtop(obj), y, mc.OBJ_mbottom(obj)) ;
  165.   END IsInObject;
  166.  
  167. VAR
  168.   data : POINTER TO Data ;
  169.  
  170. BEGIN
  171.   data := mc.InstData(cl, obj) ;
  172.  
  173.   IF msg^.muikey # 0 THEN
  174.     CASE msg^.muikey OF
  175.     | mc.MUIKEYLEFT  : data^.sx := -1 ; IF ml.moRedraw(obj, CAST(LONGCARD, mc.MADFlagSet{mc.drawUpdate})) # NIL THEN END ;
  176.     | mc.MUIKEYRIGHT : data^.sx :=  1 ; IF ml.moRedraw(obj, CAST(LONGCARD, mc.MADFlagSet{mc.drawUpdate})) # NIL THEN END ;
  177.     | mc.MUIKEYUP    : data^.sy := -1 ; IF ml.moRedraw(obj, CAST(LONGCARD, mc.MADFlagSet{mc.drawUpdate})) # NIL THEN END ;
  178.     | mc.MUIKEYDOWN  : data^.sy :=  1 ; IF ml.moRedraw(obj, CAST(LONGCARD, mc.MADFlagSet{mc.drawUpdate})) # NIL THEN END ;
  179.     ELSE
  180.     END (* CASE *) ;
  181.   END (* IF *) ;
  182.  
  183.   IF msg^.imsg # NIL THEN
  184.     IF id.mouseButtons IN msg^.imsg^.class THEN
  185.       IF msg^.imsg^.code = id.selectDown THEN
  186.         IF IsInObject(msg^.imsg^.mouseX, msg^.imsg^.mouseY) THEN
  187.           data^.x := msg^.imsg^.mouseX ;
  188.           data^.y := msg^.imsg^.mouseY ;
  189.           IF ml.moRedraw(obj, CAST(LONGCARD, mc.MADFlagSet{mc.drawUpdate})) # NIL THEN END ;
  190.           ml.moRequestIDCMP(obj, id.IDCMPFlagSet{id.mouseMove}) ;
  191.         END (* IF *) ;
  192.       ELSE
  193.         ml.moRejectIDCMP(obj, id.IDCMPFlagSet{id.mouseMove}) ;
  194.       END (* IF *) ;
  195.     ELSIF id.mouseMove IN msg^.imsg^.class THEN
  196.       IF IsInObject(msg^.imsg^.mouseX, msg^.imsg^.mouseY) THEN
  197.         data^.x := msg^.imsg^.mouseX ;
  198.         data^.y := msg^.imsg^.mouseY ;
  199.         IF ml.moRedraw(obj, CAST(LONGCARD, mc.MADFlagSet{mc.drawUpdate})) # NIL THEN END ;
  200.       END (* IF *) ;
  201.     END (* IF *)
  202.   END (* IF *) ;
  203.  
  204.   RETURN DoSuperMethodA(cl, obj, msg) ;
  205. END mHandleInput ;
  206.  
  207. (*\\\*)
  208.  
  209. (*
  210. ** Here comes the dispatcher for our custom class. 
  211. ** Unknown/unused methods are passed to the superclass immediately.
  212. *)
  213.  
  214. (*/// "MyDispatcher(cl : id.IClassPtr; obj : ADDRESS; msg : ADDRESS) : ADDRESS" *)
  215.  
  216. PROCEDURE MyDispatcher(cl : id.IClassPtr; obj : ADDRESS; msg : ADDRESS) : ADDRESS ;
  217.  
  218. VAR
  219.   mid : LONGCARD ;
  220.  
  221. BEGIN
  222.   mid := CAST(id.Msg, msg)^.methodID ;
  223.  
  224.      IF mid = m.mmAskMinMax   THEN RETURN mAskMinMax(cl, obj, msg)
  225.   ELSIF mid = m.mmSetup       THEN RETURN mSetup(cl, obj, msg)
  226.   ELSIF mid = m.mmCleanup     THEN RETURN mCleanup(cl, obj, msg)
  227.   ELSIF mid = m.mmDraw        THEN RETURN mDraw(cl, obj, msg)
  228.   ELSIF mid = m.mmHandleInput THEN RETURN mHandleInput(cl, obj, msg)
  229.   ELSE
  230.     RETURN DoSuperMethodA(cl, obj, msg)
  231.   END (* CASE *) ;
  232. END MyDispatcher ;
  233.  
  234. (*\\\*)
  235.  
  236. (***************************************************************************)
  237. (* Thats all there is about it. Now lets see how things are used...        *)
  238. (***************************************************************************)
  239.  
  240. VAR
  241.   app,
  242.   window,
  243.   grp,
  244.   myObj,
  245.   text     :  id.ObjectPtr ;
  246.   mcc      :  mc.mCustomClassPtr ;
  247.   signals  :  LONGSET ;
  248.   running  := BOOLEAN{TRUE} ;
  249.   myDispatcher : ADDRESS ;
  250.   NULL     := ADDRESS{NIL} ;
  251.  
  252.   tags     :  ARRAY [0..31] OF LONGINT ;
  253.  
  254. BEGIN
  255.  
  256.   (* Create the new custom class with a call to MUI_CreateCustomClass(). *)
  257.   (* Caution: This function returns not a struct IClass, but a           *)
  258.   (* struct MUI_CustomClass which contains a struct IClass to be         *)
  259.   (* used with NewObject() calls.                                        *)
  260.   (* Note well: MUI creates the dispatcher hook for you, you may         *)
  261.   (* *not* use its h_Data field! If you need custom data, use the        *)
  262.   (* cl_UserData of the IClass structure!                                *)
  263.  
  264.   IF ml.muiMasterVersion < 11 THEN ms.fail(NULL, "You need MUI 3 to run this demo.") END;
  265.  
  266.   myDispatcher := ADR(MyDispatcher) ;
  267.   mcc := ml.moCreateCustomClass(NIL, ADR(m.mcArea), NIL, SIZE(Data), myDispatcher) ;
  268.   IF mcc = NIL THEN ms.fail(NULL, "Could not create custom class.") END ;
  269.  
  270.   mc.MakeDispatcher(MyDispatcher, mcc^.class) ;
  271.  
  272.   myObj := il.NewObjectA(mcc^.class, NIL, TAG(tags, m.maFrame,       m.mvFrameText,
  273.                                               ud.tagDone)) ;
  274.  
  275.   text := mm.TextObject(TAG(tags, m.maFrame,        m.mvFrameText,
  276.                                   m.maBackground,   m.miTextBack,
  277.                                   m.maTextContents, ADR("\ecPaint with mouse,\nscroll with cursor keys."),
  278.                             ud.tagDone)) ;
  279.  
  280.   grp := mm.GroupObject(TAG(tags, m.maGroupHoriz, FALSE,
  281.                                   mm.Child,       text,
  282.                                   mm.Child,       myObj,
  283.                             ud.tagDone)) ;
  284.  
  285.  
  286.   window := mm.WindowObject(TAG(tags, m.maWindowTitle, ADR("A rather complex custom class"),
  287.                                       m.maWindowID,    mm.MakeID("CLS3"),
  288.                                       mm.WindowContents, grp,
  289.                                 ud.tagDone)) ;
  290.  
  291.   app := mm.ApplicationObject(TAG(tags, m.maApplicationTitle,       ADR("Class3-M2"),
  292.                                         m.maApplicationVersion,     ADR("$VER: Class3-M2 11.1 (22.9.95)"),
  293.                                         m.maApplicationCopyright,   ADR("©1995, Olaf Peters, Stefan Stuntz"),
  294.                                         m.maApplicationAuthor,      ADR("Olaf Peters, Stefan Stuntz"),
  295.                                         m.maApplicationDescription, ADR("Demonstrate the use of custom classes."),
  296.                                         m.maApplicationBase,        ADR("CLASS3M2"),
  297.                                         mm.SubWindow,               window,
  298.                                   ud.tagDone)) ;
  299.  
  300.   IF app = NIL THEN ms.fail(NULL, "Failed to create Application.") END ;
  301.  
  302.   mm.set(window,m.maWindowDefaultObject, LONGCARD(myObj)) ;
  303.  
  304.   mm.NoteClose(app, window, m.mvApplicationReturnIDQuit) ; 
  305.  
  306.  
  307. (*
  308. ** Input loop...
  309. *)
  310.  
  311.   mm.set(window, m.maWindowOpen, LONGCARD(TRUE)) ;
  312.  
  313.   WHILE running DO
  314.     CASE ms.DOMethod(app, TAG(tags, m.mmApplicationInput, ADR(signals), ud.tagDone)) OF
  315.     | m.mvApplicationReturnIDQuit : running := FALSE ;
  316.     ELSE
  317.     END (* CASE *) ;
  318.     IF running AND (signals # LONGSET{}) THEN
  319.       signals := Wait(signals) ;
  320.     END (* IF *) ;
  321.   END (* WHILE *) ;
  322.  
  323.   mm.set(window, m.maWindowOpen, LONGCARD(FALSE)) ;
  324.  
  325.  
  326. (*
  327. ** Shut down...
  328. *)
  329.  
  330. CLOSE
  331.   IF app # NIL THEN
  332.     ml.mDisposeObject(app) ;
  333.     app := NIL ;
  334.   END (* IF *) ;
  335.  
  336.   IF mcc # NIL THEN
  337.     IF ml.moDeleteCustomClass(mcc) THEN END ;
  338.     mcc := NIL ;
  339.   END (* IF *) ;
  340. END Class3.
  341.